//
//  ApiFetcher.swift
//  DaGlass
//
//  Created by 李然 on 2023/6/2.
//

import Foundation
import RxSwift
import Moya
import Alamofire

public struct ApiResultCode {
    public static let success        = 200
}

public struct DownloadResponse {
    public var code = 0
    public var url: URL?
    public var progress: Progress?
}

private let Provider = MoyaProvider<MultiTarget>()

public enum ApiFetcher {
    
    /// 请求Json类型数据
    /// - Parameter request: Alamofire 请求
    /// - Returns: 返回模型
    static func fetch<R: Decodable>(_ request: URLRequestConvertible,
                                    type: R.Type) -> Observable<R> {
        return Single<R>.create { o in
            
            let cancelable = AF.request(request).responseDecodable(of: type) { response in
                switch response.result {
                case .success(let value):
                    o(.success(value))
                    debugPrint("StravaApiFetch rxFetch 结果 ===== \n\(value)")
                case .failure(let failure):
                    debugPrint(failure.localizedDescription)
                    o(.failure(failure))
                }
            }
            
            return Disposables.create {
                cancelable.cancel()
            }
        }.asObservable()
    }
    
    public static func rxFetch<T: TargetType>(_ target: T) -> Observable<Data> {
        return Provider.rx.request(MultiTarget(target)).asObservable()
            .map { response in
                return response.data
            }
    }
    
    ///  文件下载
    /// - Parameter target: 请求
    /// - Returns: 进度和结果
    public static func rxDownload(_ target: DownloadAPI) -> Observable<DownloadResponse> {
        let o = Observable<DownloadResponse>.create { (o) -> Disposable in
            
            if target.isLocalExists {
                let progress = Progress()
                if let fileInfo = try? FileManager.default.attributesOfItem(atPath: target.localLocation.path),
                    let length = fileInfo[.size] as? Int64 {
                    progress.totalUnitCount = length
                    progress.completedUnitCount = length
                }
                var r = DownloadResponse()
                r.url = target.localLocation
                r.progress = progress
                r.code = ApiResultCode.success
                o.onNext(r)
                o.onCompleted()
                
                return Disposables.create {}
            }
            
            let d = Provider.rx.requestWithProgress(MultiTarget(target)).subscribe { pResponse in
                var r = DownloadResponse()
                r.url = target.localLocation
                r.progress = pResponse.progressObject
                r.code = pResponse.response?.statusCode ?? 0
                o.onNext(r)
            } onError: { error in
                o.onError(error)
            } onCompleted: {
                o.onCompleted()
            }
            return Disposables.create {
                d.dispose()
            }
        }
        return o
    }
}
